﻿namespace Digitalmes.Application.Mes;

/// <summary>
/// 生产报表
/// </summary>
[ApiExplorerSettings(GroupName = "mes")]
[AllowAnonymous]
public sealed class ReportProductionService : IDynamicWebApiService
{
    private readonly SugarRepository<ProdTransSnRecord> _tranSnRecordRepo;
    private readonly SugarRepository<MdShift> _shiftRepo;
    private readonly SugarRepository<ProdTask> _taskRepo;

    public ReportProductionService(
        SugarRepository<ProdTransSnRecord> tranSnRecordRepo,
        SugarRepository<MdShift> shiftRepo,
        SugarRepository<ProdTask> taskRepo)
    {
        _tranSnRecordRepo = tranSnRecordRepo;
        _shiftRepo = shiftRepo;
        _taskRepo = taskRepo;
    }

    /// <summary>
    /// 生产统计
    /// </summary>
    /// <returns></returns>
    [HttpGet]
    public async Task<object> GetStatAsync(string? datetime = null)
    {
        // 分区域统计班次的计划数量、实际完成数量以及比例

        var now = !string.IsNullOrEmpty(datetime) ? DateTime.Parse(datetime) : DateTime.Now;
        var startTime = now.Date; // 默认按午夜 00:00:00 计算
        MdShift? currentShift = null; // 当前班次，默认 null

        // 找到当前时间归属的班次
        // 若当前时间在班次内，那么按该班次事件算；
        // 思考：若当前时间不在班次内，是否可以找当前时间最近结束的那个班次？
        var shifts = await _shiftRepo.GetListAsync();
        if (shifts.Count > 0)
        {
            var shift = shifts.FirstOrDefault(s => s.IsIn(now));
            if (shift != null)
            {
                currentShift = shift;

                TimeOnly start = TimeOnly.Parse(shift.BeginTime);
                TimeOnly end = TimeOnly.Parse(shift.EndTime);
                if (start < end)
                {
                    startTime = now.Date.Add(start.ToTimeSpan());
                }
                else // 跨天
                {
                    startTime = now.Date.AddDays(-1).Add(start.ToTimeSpan());
                }
            }
        }

        // 查找当前计划任务
        var shiftCode = currentShift?.ShiftCode;
        var tasks = await _taskRepo.GetListAsync(m => m.ShiftCode == shiftCode);

        // 每个区域尾部工序编号（区域编号固定为 "01"、"02" 和 "03"，与地址表设备配置一致）
        var area1Task = tasks.FirstOrDefault(t => t.Area == "01");
        var area2Task = tasks.FirstOrDefault(t => t.Area == "02");
        var area3Task = tasks.FirstOrDefault(t => t.Area == "03");

        var area1TailProcCode = area1Task?.TailProcCode ?? "OP300"; // OP300 若未设置区域尾部工序，则用默认的
        var area2TailProcCode = area2Task?.TailProcCode ?? "OP360"; // OP360
        var area3TailProcCode = area3Task?.TailProcCode ?? "OP410"; // OP410

        // 查找当前生产数量
        var query = await _tranSnRecordRepo.AsQueryable()
           .Where(s => s.OutboundTime >= startTime && s.RoutingId > 0 && s.PassResult == PassResultEnum.OK)
           .Select(x => new
           {
               area1Count = SqlFunc.AggregateDistinctCount(SqlFunc.IIF(x.ProcCode == area1TailProcCode, x.Sn, null)), // COUNT 函数仅统计非 Null 值的记录
               area2Count = SqlFunc.AggregateDistinctCount(SqlFunc.IIF(x.ProcCode == area2TailProcCode, x.Sn, null)),
               area3Count = SqlFunc.AggregateDistinctCount(SqlFunc.IIF(x.ProcCode == area3TailProcCode, x.Sn, null)),
           })
           .FirstAsync();

        // 没设定则与实际生产数相等
        var area1TaskCount = area1Task?.Qty ?? query.area1Count;
        var area2TaskCount = area2Task?.Qty ?? query.area2Count;
        var area3TaskCount = area3Task?.Qty ?? query.area3Count;

        return new
        {
            shiftName = currentShift?.ShiftName ?? "--", // 当前班次
            areas = new object[]
            {
                new
                {
                    areaName = "一",
                    taskCount = area1TaskCount,
                    actualCount = query.area1Count,
                    rate = CalProductionRate(query.area1Count, area1TaskCount),
                },
                new
                {
                    areaName = "二",
                    taskCount = area2TaskCount,
                    actualCount = query.area2Count,
                    rate = CalProductionRate(query.area2Count, area2TaskCount),
                },
                new
                {
                    areaName = "三",
                    taskCount = area3TaskCount,
                    actualCount = query.area3Count,
                    rate = CalProductionRate(query.area3Count, area3TaskCount),
                },
            },
        };

        static string CalProductionRate(int actualCount, int taskCount)
        {
            if (actualCount == 0)
            {
                return "0.0%";
            }

            if (taskCount == 0)
            {
                return "100%";
            }

            var rate = Math.Round((decimal)actualCount / taskCount, 4);
            return rate.ToString("P1"); // 转换为百分比，默认保留 2 位小数，可使用 "P1"、"P2" 等指定小数位
        }
    }
}
